

const PENDDING= 'pendding'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class LPromise {
  FULFILLED_CB_LIST= []
  REJECTED_CB_LIST = []
  constructor (fn) {
    this.value = undefined
    this.reason = undefined
    this.status = PENDDING
    try {
      fn(this.resolve.bind(this), this.reject.bind(this))
    } catch (error) {
      this.reject(error)
    }
  }
  resolve(value) {
    if (this.status === PENDDING) {
      this.status = FULFILLED
      this.value = value
      if(this.FULFILLED_CB_LIST.length){
        this.FULFILLED_CB_LIST.forEach(cb=>cb(this.value))
      }
    }
  }
  reject(reason){
    if (this.status === PENDDING){
      this.status = REJECTED
      this.reason = reason
      if(this.REJECTED_CB_LIST.length){
        this.REJECTED_CB_LIST.forEach(cb=>cb(this.reason))
      }
    }
  }
  then(onFulfilled, onRejected){
    const realFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value => value
    const realRejected = this.isFunction(onRejected) ? onRejected : reason=>{throw Error(reason)}
    const promise2 = new LPromise((resolve,reject)=>{
      const fulflledMircotask = ()=>{
        queueMicrotask (()=>{
          try {
            const x = realFulfilled(this.value)
            this.resolvePromise(promise2,x,resolve,reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      const rejectedMircotask = ()=>{
        queueMicrotask(()=>{
          try {
            const x = realRejected(this.reason)
            this.resolvePromise(promise2,x,resolve,reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      switch (this.status) {
        case FULFILLED: {
          fulflledMircotask()
          break
        }
        case REJECTED: {
          rejectedMircotask()
          break
        }
        case PENDDING:{
          this.FULFILLED_CB_LIST.push(fulflledMircotask)
          this.REJECTED_CB_LIST.push(rejectedMircotask)
          break
        }
      }
    })
    return promise2
  }
  resolvePromise(promise2,x,resolve,reject){
    if (promise2 === x) {
      return reject(new TypeError('can not return the same value'))
    }
    if (x instanceof LPromise) {
      queueMicrotask(()=>{
        x.then(
          y=>{
            this.resolvePromise(promise2,y,resolve,reject)
          },
          r=>{
            reject(r)
          }
        )
      })
    }
    if (x === null) {
      return resolve(x)
    }
    if (typeof x === 'object' || this.isFunction(x)) {
      let then
      try {
        then = x.then
        if (this.isFunction(then)) {
          let used = false
          then.call(
            x,
            y=>{
              if(used) return
              used = true
              this.resolvePromise(promise2,y,resolve,reject)
            },
            r=>{
              if(used) return
              used = true
              reject(r)
            }
            )
        } else {
          resolve(x)
        }
      } catch (error) {
        reject(error)
      }
    } else {
      resolve(x)
    }
  }
  isFunction(fn){
    return typeof fn === 'function'
  }
}

var p1 = new LPromise((resolve,reject)=>{
  resolve('111')
}).then((res)=>{
  console.log('res',res)
  return 'resolve1111'
},r=>{
  console.log('r',r)
  return 'reject1111'
}).then(res=>{
  console.log('d第二个then的res',res)
})